#!/bin/sh

# firewall is part of code.google.com/p/camtools,
# Copyright 2007 Camille Huot,
# Licensed under http://www.gnu.org/copyleft/gpl.html


## firewall for efika.cameuh.net
## 20070809 -- cam


ipt="/sbin/iptables"

function policy () {
 $ipt -P $1 $2
}

function begin () {
 for cmd in F X; do for table in filter nat; do
  $ipt -t $table -$cmd
 done; done
 policy INPUT DROP
 $ipt -A INPUT -i lo -j ACCEPT
 $ipt -A OUTPUT -o lo -j ACCEPT
 $ipt -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 $ipt -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 $ipt -A INPUT -p ICMP -j ACCEPT
 $ipt -A OUTPUT -p ICMP -j ACCEPT
}

function end () {
exit
}

function nat () {
 $ipt -t nat -A POSTROUTING -o $1 -j MASQUERADE
}

# syntax: makearg "value" "default_value" "option name"
function makearg () {
 if [ $# -ne 3 ]; then echo "makearg requires 3 args (gets '$@')"; exit; fi
 [ "$1" != "$2" ] && echo "$3 $1"
}

function rdr () {
# nat [pass [log]] on interface [af] from src_addr [port src_port] to \
#dst_addr [port dst_port] -> ext_addr [pool_type] [static-port]
protos="all"
ports="any"
froms="any"
to="any"
while [ $# -gt 0 ]; do
 case "$1" in
  proto)
   protos="$2"
   shift
   ;;
  from)
   froms="$2"
   shift
   ;;
  to)
   dests="$2"
   shift
   if [ "$2" = "port" ]; then
    ports="$3"
    shift
    shift
   fi
   ;;
  =)
   dst="$2"
   if [ "$3" = "port" ]; then
    dst=$dst":$4"
   fi
   break
   ;;
  pass)
   ;;
  *)
   ;;
 esac
 shift
done
for dest in $dests; do
 dest="$(makearg $dest any -d)"
 for proto in $protos; do
  proto="$(makearg $proto all -p)"
  for from in $froms; do
   from="$(makearg $from any -s)"
   for port in $ports; do
    port="$(makearg $port any --dport)"
    $ipt -t nat -A PREROUTING $proto $from $dest $port -j DNAT --to-destination $dst
   done
  done
 done
done
}

function block () {
# block in on $wan_if
# iptables -A INPUT -i $ADM_IF -p tcp -s 10.234.65.171 --dport 1521 -j ACCEPT
 directions="in out"
 protos="all"
 froms="any"
 dests="any"
 dports="any"
 interfaces="any"
 #action [direction] [log] [quick] [on interface] [af] [proto protocol] \
 #[from src_addr [port src_port]] [to dst_addr [port dst_port]] \
 #[flags tcp_flags] [state]
 if [ "${FUNCNAME[1]}" = "pass" ]; then
  action="ACCEPT"
 else
  action="DROP"
 fi
 while [ $# -gt 0 ]; do
  case $1 in
   in)
    directions="in"
    ;;
   out)
    directions="out"
    ;;
   on)
    interfaces="$2"
    shift
    ;;
   proto)
    protos="$2"
    shift
    ;;
   from)
    froms="$2"
    shift
    ;;
   to)
    dests="$2"
    shift
    if [ "$2" = "port" ]; then
     dports="$3"
     shift
     shift
    fi
    ;;
   *)
    ;;
  esac
  shift
 done
 case $directions in
  in)
   chains="INPUT FORWARD"
   ;;
  out)
   chains="OUTPUT FORWARD"
   ;;
  "in out")
   chains="INPUT OUTPUT FORWARD"
   ;;
  *)
   echo "unable to determine chain to block/allow"
   exit
   ;;
  esac
 for chain in $chains; do
  for proto in $protos; do
   proto="$(makearg $proto all -p)"
   for from in $froms; do
    from="$(makearg $from any -s)"
    for dest in $dests; do
     dest="$(makearg $dest any -d)"
     for dport in $dports; do
      dport="$(makearg $dport any --dport)"
      for interface in $interfaces; do
       if [ "$chain" = "FORWARD" ]; then
        interface=""
       else
        interface="$(makearg $interface any -$(echo ${chain:0:1}|tr 'IO' 'io'))"
       fi
       $ipt -A $chain $interface $proto $from $dest $dport -j $action
      done
     done
    done
   done
  done
 done
}

function pass () {
 block "$@"
}


begin
source /etc/firewall.conf
end
